-- roomService存储用户的信息,定期写入服务器
local skynet = require "skynet"
local CMD = {}

local Room = require "src.db.Room"
local PlayerInRoom = require "src.db.PlayerInRoom"

local rooms = {}

local userInfos = {}

local userService

-- 工具函数
local function leaveRoom(info)
    local preRoom = rooms[info.roomId]
    Room:QuitByName(preRoom, info.username)
    userInfos[info.username] = nil
end

local function getAgentByUsername(username)
    return skynet.call(userService, "lua", "getAgentByUsername", {
        username = username
    })
end

local function startByUsername(username)
    -- 获取该user的agent
    local agent = getAgentByUsername(username)
    skynet.call(agent, "lua", "gameStart")
end

local function checkReady(roomId)
    -- 检查房间中玩家是否满、是否已准备，如果是的话向它们发送开始消息
    local room = rooms[roomId]
    if room.playerNum == room.playerNumMax then
        -- 人数已满，检查准备
        if Room:IsReady(room) then
            -- 准备好了，开！
            for i, player in ipairs(room.players) do
                local username = player.username
                room.isPlaying = true
                startByUsername(username)
            end
        end
    end
end

-- 服务间通信
function CMD.getRooms()
    return rooms
end

function CMD.leaveRoom(args)
    local username = args.username
    local info = userInfos[username]
    if info ~= nil then
        leaveRoom(info)
    end
end

function CMD.enterRoom(args)
    local roomId = args.roomId
    local username = args.username
    local room = rooms[roomId]
    print("用户[" .. username .. "]想要进入房间" .. roomId)
    -- 先判断用户是否在房间中
    if userInfos[username] == nil then
        -- 不在，暂时不需要处理
    else
        local info = userInfos[username]
        if info.isReady then
            -- 在房间中，准备的不能换房间
            return nil
        else
            -- 已经在房间中，需要先退出之前的房间
            leaveRoom(info)
        end
    end
    -- 加入房间
    local info = PlayerInRoom:New(username, roomId, false)
    userInfos[username] = info
    Room:AddPlayer(room, info)
    return info
end

function CMD.ready(args)
    local username = args.username
    -- 先判断用户是否在房间中
    local info
    if userInfos[username] == nil then
        -- 不在，暂时不需要处理
        return nil
    else
        -- 找到用户所在的房间
        info = userInfos[username]
    end
    local room = rooms[info.roomId]
    -- 改为准备
    Room:ReadyByName(room, username)
    info.isReady = true

    -- 检测准备情况，决定是否直接开局
    checkReady(info.roomId)
    return info
end

function CMD.unready(args)
    local username = args.username
    -- 先判断用户是否在房间中
    local info
    if userInfos[username] == nil then
        -- 不在，暂时不需要处理
        return nil
    else
        -- 找到用户所在的房间
        info = userInfos[username]
    end
    local room = rooms[info.roomId]
    -- 改为准备
    Room:UnReadyByName(room, username)
    info.isReady = false
    return info
end

function CMD.sendBattleData(args)
    local roomId = args.roomId
    local data = args.data
    local sender = args.sender

    local room = rooms[roomId]
    for i, player in ipairs(room.players) do
        local username = player.username
        if username ~= sender then
            -- 对它发送data
            local agent = getAgentByUsername(username)
            data.username = username
            skynet.call(agent, "lua", "battleData", {
                data = data
            })
        end
    end
end

local function InitRooms()
    -- 初始化房间，8个1v1房间无人状态
    for i = 1, 8, 1 do
        rooms[i] = Room:NewDefault(i)
    end
end

function CMD.start(conf)
    userService = skynet.queryservice("userService")
    InitRooms()
end

skynet.start(function()
    skynet.dispatch("lua", function(_, _, command, ...)
        local f = CMD[command]
        skynet.ret(skynet.pack(f(...)))
    end)
end)
